﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using csLTDMC;
using InspectionMAC.Function;
using InspectionMAC.Forms;
using InspectionMAC.SystemThread;

namespace InspectionMAC.Config
{
    public static class BuilderManager
    {
        private static readonly object _syncRoot = new object();
        private static readonly ConcurrentDictionary<string, SingleItemInfoBuilder> _builders =
            new ConcurrentDictionary<string, SingleItemInfoBuilder>();

        private static Timer _cleanupTimer;
        private const int CLEANUP_INTERVAL = 30000;
        private const int TIMEOUT_SECONDS = 120;

        private static readonly Queue<DateTime> _completionTimes = new Queue<DateTime>();
        private static readonly object _rateLock = new object();
        private const int RATE_CALCULATION_WINDOW = 5;

        private static Timer _rateUpdateTimer;
        private const int RATE_UPDATE_INTERVAL = 1000; // 每秒更新一次

        private static void RecordCompletionTime()
        {
            lock (_rateLock)
            {
                DateTime now = DateTime.Now;
                _completionTimes.Enqueue(now);

                DateTime cutoff = now.AddSeconds(-RATE_CALCULATION_WINDOW);
                while (_completionTimes.Count > 0 && _completionTimes.Peek() < cutoff)
                {
                    _completionTimes.Dequeue();
                }
            }
        }

        public static int GetCurrentDetectionRateAsInt()
        {
            lock (_rateLock)
            {
                DateTime cutoff = DateTime.Now.AddSeconds(-5);
                while (_completionTimes.Count > 0 && _completionTimes.Peek() < cutoff)
                {
                    _completionTimes.Dequeue();
                }

                int countIn5Seconds = _completionTimes.Count;
                return countIn5Seconds == 0 ? 0 : countIn5Seconds * 12;
            }
        }

        public static void ResetRateStatistics()
        {
            lock (_rateLock)
            {
                _completionTimes.Clear();
            }
            Console.WriteLine("速率统计已重置");
        }

        public static string GetRateInfo()
        {
            lock (_rateLock)
            {
                DateTime now = DateTime.Now;
                DateTime cutoff = now.AddSeconds(-RATE_CALCULATION_WINDOW);

                int count = 0;
                while (_completionTimes.Count > 0 && _completionTimes.Peek() < cutoff)
                {
                    _completionTimes.Dequeue();
                }
                count = _completionTimes.Count;

                double ratePerMinute = count == 0 ? 0 : count * 12;
                return $"最近5秒完成: {count}个, 速率: {ratePerMinute:F1}个/分钟";
            }
        }

        /// <summary>
        /// 定时更新速率显示，当没有物料完成时自动归零
        /// </summary>
        private static void UpdateRateMinutes(object state)
        {
            try
            {
                lock (_rateLock)
                {
                    DateTime now = DateTime.Now;
                    DateTime cutoff = now.AddSeconds(-RATE_CALCULATION_WINDOW);

                    // 清理过期的完成时间记录
                    while (_completionTimes.Count > 0 && _completionTimes.Peek() < cutoff)
                    {
                        _completionTimes.Dequeue();
                    }

                    int countIn5Seconds = _completionTimes.Count;

                    // 如果5秒内没有完成记录，则速率归零
                    if (countIn5Seconds == 0)
                    {
                        SingleItemInfoBuilder.RateMinutes = "0";
                    }
                    else
                    {
                        // 有完成记录时正常计算速率
                        int ratePerMinute = countIn5Seconds * 12;
                        SingleItemInfoBuilder.RateMinutes = ratePerMinute.ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"更新速率显示异常: {ex.Message}");
                // 异常时也归零
                SingleItemInfoBuilder.RateMinutes = "0";
            }
        }

        public static void Initialize()
        {
            _cleanupTimer = new Timer(
                CleanupExpiredBuilders,
                null,
                CLEANUP_INTERVAL,
                CLEANUP_INTERVAL
            );

            // 新增速率更新定时器
            _rateUpdateTimer = new Timer(UpdateRateMinutes, null, RATE_UPDATE_INTERVAL, RATE_UPDATE_INTERVAL);
        }

        static BuilderManager()
        {
            _cleanupTimer = new Timer(CleanupExpiredBuilders, null, CLEANUP_INTERVAL, CLEANUP_INTERVAL);
            // 新增速率更新定时器
            _rateUpdateTimer = new Timer(UpdateRateMinutes, null, RATE_UPDATE_INTERVAL, RATE_UPDATE_INTERVAL);
        }

        public static void UpdateBuilderForCamera1(string productId, string productName, string materialId,
                                                  CameraResult01 result)
        {
            try
            {
                lock (_syncRoot)
                {
                    var builder = _builders.GetOrAdd(materialId, id =>
                        new SingleItemInfoBuilder
                        {
                            ProductId = productId,
                            ProductName = productName,
                            SampleId = materialId,
                            LastUpdateTime = DateTime.Now
                        });

                    builder.SetResult01(result);
                    builder.LastUpdateTime = DateTime.Now;

                    Console.WriteLine($"更新工位1结果: 物料{materialId}, NG={result.isNG}, 缺陷:{result.Faults}");
                    GetCameraImgThread01.isNG = result.isNG;
                    builder.TryComplete();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"更新工位1结果异常: {ex.Message}");
            }
        }

        public static void UpdateBuilderForCamera2(string productId, string productName, string materialId,
                                          CameraResult02 result)
        {
            try
            {
                lock (_syncRoot)
                {
                    var builder = _builders.GetOrAdd(materialId, id =>
                        new SingleItemInfoBuilder
                        {
                            ProductId = productId,
                            ProductName = productName,
                            SampleId = materialId,
                            LastUpdateTime = DateTime.Now
                        });

                    builder.SetResult02(result);
                    builder.LastUpdateTime = DateTime.Now;
                    Console.WriteLine($"更新工位2结果: 物料{materialId}, NG={result.isNG}, 缺陷:{result.Faults}");
                    GetCameraImgThread02.isNG = result.isNG;
                    builder.TryComplete();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"更新工位2结果异常: {ex.Message}");
            }
        }

        public static void UpdateBuilderForCamera3(string productId, string productName, string materialId,
                                                  CameraResult03 result)
        {
            try
            {
                lock (_syncRoot)
                {
                    var builder = _builders.GetOrAdd(materialId, id =>
                        new SingleItemInfoBuilder
                        {
                            ProductId = productId,
                            ProductName = productName,
                            SampleId = materialId,
                            LastUpdateTime = DateTime.Now
                        });

                    builder.SetResult03(result);
                    builder.LastUpdateTime = DateTime.Now;
                    Console.WriteLine($"更新工位3结果: 物料{materialId}, NG={result.isNG}, 缺陷:{result.Faults}");
                    GetCameraImgThread03.isNG = result.isNG;
                    builder.TryComplete();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"更新工位3结果异常: {ex.Message}");
            }
        }

        // 移除物料构建器（在踢料或正常通过后调用）
        public static void RemoveMaterialAfterKick(string materialId)
        {
            lock (_syncRoot)
            {
                if (string.IsNullOrWhiteSpace(materialId))
                {
                    Console.WriteLine("警告: 尝试移除空物料ID");
                    return;
                }

                SingleItemInfoBuilder builder;
                if (_builders.TryRemove(materialId, out builder))
                {
                    RecordCompletionTime();
                    Console.WriteLine($"踢料后移除物料构建器: {materialId}");
                }
                else
                {
                    Console.WriteLine($"警告: 未找到物料{materialId}的构建器");
                }
            }
        }

        private static void CleanupExpiredBuilders(object state)
        {
            try
            {
                Console.WriteLine($"开始清理[超时/完成]构建器 [当前总数: {_builders.Count}]");

                DateTime now = DateTime.Now;
                var samplesToRemove = new List<string>();

                foreach (var kvp in _builders)
                {
                    var builder = kvp.Value;

                    // 1. 检查已完成样本（完成后超过30秒）
                    if (builder.HasCompleted && (now - builder.CompletionTime).TotalSeconds > 30)
                    {
                        samplesToRemove.Add(kvp.Key);
                        Console.WriteLine($"清理已完成物料: {kvp.Key}, 完成于: {builder.CompletionTime:HH:mm:ss}");
                    }
                    // 2. 检查超时样本（2分钟无更新）
                    else if (!builder.HasCompleted && (now - builder.LastUpdateTime).TotalSeconds > TIMEOUT_SECONDS)
                    {
                        samplesToRemove.Add(kvp.Key);
                        Console.WriteLine($"清理超时物料: {kvp.Key}, 最后更新时间: {builder.LastUpdateTime:HH:mm:ss}");
                    }
                }

                if (samplesToRemove.Count == 0)
                {
                    Console.WriteLine("无需清理");
                }
                else
                {
                    foreach (var materialId in samplesToRemove)
                    {
                        Console.WriteLine($"清理物料: {materialId}");
                        RemoveMaterialAfterKick(materialId);
                    }
                    Console.WriteLine($"清理完成, 移除物料数: {samplesToRemove.Count}");
                }

                Console.WriteLine($"当前活动构建器数量: {_builders.Count}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"清理构建器异常: {ex.Message}");
            }
        }
    }

    public class SingleItemInfoBuilder
    {
        public string ProductId { get; set; } = string.Empty;
        public string ProductName { get; set; } = string.Empty;
        public string SampleId { get; set; } = string.Empty;
        public DateTime LastUpdateTime { get; set; } = DateTime.MinValue;

        public CameraResult01? Result01 { get; private set; } = null;
        public CameraResult02? Result02 { get; private set; } = null;
        public CameraResult03? Result03 { get; private set; } = null;

        public static int totalCounts = 0;
        public static int NGCounts = 0;
        public static int OKCounts = 0;

        public void SetResult01(CameraResult01 result)
        {
            Result01 = result;
        }

        public void SetResult02(CameraResult02 result)
        {
            Result02 = result;
        }

        public void SetResult03(CameraResult03 result)
        {
            Result03 = result;
        }

        public static void ClearCounts()
        {
            if (totalCounts != 0)
            {
                BuilderManager.ResetRateStatistics();
            }
            NGCounts = 0;
            OKCounts = 0;
            totalCounts = 0;

            Camera1NGCounts = 0;
            Camera1OKCounts = 0;
            Camera1TotalCounts = 0;

            Camera2NGCounts = 0;
            Camera2OKCounts = 0;
            Camera2TotalCounts = 0;

            Camera3NGCounts = 0;
            Camera3OKCounts = 0;
            Camera3TotalCounts = 0;
        }

        public static int Camera1TotalCounts;
        public static int Camera1NGCounts;
        public static int Camera1OKCounts;

        public static int Camera2TotalCounts;
        public static int Camera2NGCounts;
        public static int Camera2OKCounts;

        public static int Camera3TotalCounts;
        public static int Camera3NGCounts;
        public static int Camera3OKCounts;

        // 确保 RateMinutes 有默认值
        public static string RateMinutes { get; set; } = "0";

        public void TryComplete()
        {
            lock (this)
            {
                try
                {
                    if (Result01 != null && Result02 != null && Result03 != null)
                    {
                        // 计算是否有缺陷
                        bool camera1NG = Result01.HasValue && Result01.Value.isNG;
                        bool camera2NG = Result02.HasValue && Result02.Value.isNG;
                        bool camera3NG = Result03.HasValue && Result03.Value.isNG;
                        bool hasNG = (camera1NG || camera2NG || camera3NG);

                        // 设置踢料标记
                        bool needKick = hasNG;
                        Console.WriteLine($"物料检测结果: 相机1NG={camera1NG}, 相机2NG={camera2NG}, 相机3NG={camera3NG}, 有缺陷={hasNG}, 需要踢料={needKick}");

                        // 强制踢料模式
                        if (MacTestForm.macTestForm.isForceKick)
                        {
                            needKick = true;
                            Console.WriteLine($"强制踢料模式: 物料{SampleId}将被踢出");
                        }

                        // 创建完整数据项
                        var item = new SingleItemInfo
                        {
                            ID = this.ProductId,
                            Name = this.ProductName,
                            SampleId = this.SampleId,
                            CameraResult01 = Result01.Value,
                            CameraResult02 = Result02.Value,
                            CameraResult03 = Result03.Value,
                            CreationTime = DateTime.Now.ToString("yyyyMMddHHmmss"),
                            NeedKick = needKick,
                        };

                        if (DataStorageToExcelThread.EnqueueData(item))
                        {
                            Console.WriteLine($"已添加到Excel存储队列: {SampleId}");
                        }
                        else
                        {
                            Console.WriteLine($"警告: 添加到Excel队列失败: {SampleId}");
                        }

                        // 更新计数
                        if (needKick)
                        {
                            NGCounts += 1;
                            Console.WriteLine($"NG物料计数增加: {SampleId}");
                        }
                        else
                        {
                            OKCounts += 1;
                            Console.WriteLine($"OK物料计数增加: {SampleId}");
                        }
                        totalCounts += 1;

                        // 如果需要踢料，添加到踢料队列
                        if (needKick)
                        {
                            var material = MaterialTracker.GetMaterialInfo(SampleId);
                            if (material != null)
                            {
                                KickQueueManager.AddToKickQueue(SampleId, material.CreationTime);
                                MaterialTracker.SetKickInfo(SampleId, true, false);
                                Console.WriteLine($"物料标记为需要踢料并添加到队列: {SampleId}, 创建时间: {material.CreationTime:HH:mm:ss.fff}");
                            }
                            else
                            {
                                Console.WriteLine($"警告: 未找到物料{SampleId}，无法添加到踢料队列");
                            }
                        }

                        // 重要修改：所有物料都不立即移除，只标记为完成并等待踢料传感器
                        HasCompleted = true;
                        CompletionTime = DateTime.Now;

                        // 更新物料状态为等待踢料判断
                        MaterialTracker.UpdateMaterialStatus(SampleId, MaterialTracker.MaterialStatus.WaitingForKickDecision);

                        Console.WriteLine($"物料检测完成，等待踢料判断: {SampleId}, 需要踢料: {needKick}");
                        // 注意：这里不再直接更新RateMinutes，由定时器统一管理
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"构建器完成检测异常: 物料{SampleId}, {ex.Message}");
                }
            }
        }

        public bool HasCompleted { get; private set; } = false;
        public DateTime CompletionTime { get; private set; } = DateTime.MinValue;

        public override string ToString()
        {
            return $"{SampleId} [产品: {ProductId}-{ProductName}, 更新时间: {LastUpdateTime:HH:mm:ss}]";
        }

        private const uint KICK_OFFSET = 75262;
        private const ushort KICK_DO_PIN = 10;
        private const ushort KICK_ACTION_TYPE = 8;

        public const bool isForceKick = false;
    }
}